IntimateMerger Analytics Adapter : initial release#21
Conversation
|
Tread carefully! This PR adds 1 linter error (possibly disabled through directives):
|
|
Tread carefully! This PR adds 1 linter error (possibly disabled through directives):
|
|
Tread carefully! This PR adds 1 linter error (possibly disabled through directives):
|
fecker
left a comment
There was a problem hiding this comment.
ちともろもろ確認したいのと、意識合わせしたいです。
各社のAnalytics Adaptor は、bid の分析をもろもろしているのですが、
IMでは不要なので、そのあたりは調整が必要かなと。
今の実装ならキャッシュは不要な気がしつつ、バッファリング送信機能をつけるなら必要になるかなと思っています。
- AUCTION_INIT
- cache の初期化(auctionId の管理用)
- Consent データの初期化 (auctionId に紐づけて管理)
- pvデータのみを送信(ちょっと悩み中。データとして使わないなら、ぶっちゃけまとめて送ってもいいかも? 調整中)
- AUCTION_END
- setTimeout で遅延実行(800 ms くらい?)
- cache[auctionId] に入ってるものを送る
- cache[auctionId] で、データ送信フラグ を管理
- setTimeout で遅延実行(3分後くらい?)
- cache[auctionId] を削除する
− SPA でたまらないようにする
- cache[auctionId] を削除する
- setTimeout で遅延実行(800 ms くらい?)
- BID_WON
- cache[auctionId] に 情報を蓄積する
- データ送信済だったら(フラグがたってたら)全データを再送する
実装イメージ
case EVENTS.AUCTION_END:
setTimeout(() => {
analyticsAdapter.sendEvents(args.auctionId);
}, BID_WON_WAIT); // 800ms ?
break;
こんなことを書いてる Adaptor がいるので、バッファリングいけるんじゃないかと思ってます。
case EVENTS.BID_WON:
const auction = cache.auctions[args.auctionId];
if (!auction) return;
// transactionId 単位で、cache するか
// 配列に push した方が楽かもしれない
// 再送を考えて、Timestamp も入れてもいいかも
if (auction.sendStatus & REQUEST_SENT) { // すでに送信済だったら
analyticsAdapter.sendEvents(args.auctionId); // 再送する
}
みたいな感じでいけたりしないかなぁと思ってきました。
許諾のデータは、
libraries/intentIqUtils/getCmpData.js を参考にして
gdpr と usp (ccpa) だけとっておくと幸せになれるかなとおもってきました。
import { allConsent } from '../../src/consentHandler.js';
/**
* Retrieves consent data from the Consent Management Platform (CMP).
* @return {Object} An object containing the following fields:
* - `gdprString` (string): GDPR consent string if available.
* - `uspString` (string): USP consent string if available.
* - `gppString` (string): GPP consent string if available.
*/
export function getCmpData() {
const consentData = allConsent.getConsentData();
return {
gdprApplies: consentData?.gdpr?.gdprApplies || false,
gdprString: typeof consentData?.gdpr?.consentString === 'string' ? consentData.gdpr.consentString : null,
uspString: typeof consentData?.usp === 'string' ? consentData.usp : null,
gppString: typeof consentData?.gpp?.gppString === 'string' ? consentData.gpp.gppString : null,
};
}
|
|
Tread carefully! This PR adds 2 linter errors (possibly disabled through directives):
|
|
Tread carefully! This PR adds 2 linter errors (possibly disabled through directives):
|
|
Tread carefully! This PR adds 2 linter errors (possibly disabled through directives):
|
modules/imAnalyticsAdapter.js
Outdated
| gdprApplies: gdprConsent.gdprApplies, | ||
| gdpr: gdprConsent.consentString, |
There was a problem hiding this comment.
gdpr の consent はいらないかなと思ってきました・・・・(対応するつもりがほぼない)
他の adapter でやってたのですが gdpr に true / false (gdprApplies) を渡して、あげるのが幸せになれるかと思いました。
There was a problem hiding this comment.
| gdprApplies: gdprConsent.gdprApplies, | |
| gdpr: gdprConsent.consentString, | |
| gdpr: gdprConsent.gdprApplies ? 1 : 0, |
と短くしてなるべく小さくした方が良さげかなと。
modules/imAnalyticsAdapter.js
Outdated
| return { | ||
| gdprApplies: gdprConsent.gdprApplies, | ||
| gdpr: gdprConsent.consentString, | ||
| usp: uspConsent |
There was a problem hiding this comment.
coppa も念の為取得しておいて頂けるとうれしいです。
coppa = Number(coppaDataHandler.getCoppa());
| const gdprConsent = request.gdprConsent || {}; | ||
| const uspConsent = request.uspConsent; | ||
|
|
||
| return { |
There was a problem hiding this comment.
アメリカ・カナダがそこそこ入っていたので、
ggp: gppDataHandler.getConsentData().applicableSections; (Number が入ります)
ggpString: gppDataHandler.getConsentData().gppString;
で取得をお願いします。
(真面目にやるとここを見るのが良さげ?)
modules/imAnalyticsAdapter.js
Outdated
|
|
||
| case EVENTS.AUCTION_END: | ||
| logMessage('IM Analytics: AUCTION_END', args); | ||
| this.scheduleWonBidsSend(args.auctionId); |
There was a problem hiding this comment.
細かいのですが、handleActionEnd() の方が良いのかなと思ったり。
で、その中で 2つの処理を schedule するのが良いのでは?って思いました。
別のAdapterでやってたのですが、
(あまりユースケースはないかもですが、)Cache の肥大化対策をしてるものがいました。
一定時間後(5秒 〜 10秒後)に、cache[auctions] をクリアする処理があってもいいかもす。
modules/imAnalyticsAdapter.js
Outdated
| * @param {Object} auctionArgs - Auction arguments | ||
| * @param {Object} consentData - Consent data object | ||
| */ | ||
| handleAucInitData(auctionArgs, consentData) { |
There was a problem hiding this comment.
consentData って、auction の中でキャッシュされてるので、それを使いまわした方が良いのではと思ったのですが、どうすか?
handleAuction で、引数があわないのが気持ちわるい感じがします。
modules/imAnalyticsAdapter.js
Outdated
| return; | ||
| } | ||
|
|
||
| const consentData = auction.consentData || getConsentData(null); |
There was a problem hiding this comment.
たしかにおかしなことにならないのでauction.consentDataからの取得でまとめました
modules/imAnalyticsAdapter.js
Outdated
| */ | ||
| sendWonBidsData(auctionId) { | ||
| const auction = cache.auctions[auctionId]; | ||
| if (!auction || !auction.wonBids || auction.wonBids.length === 0 || (auction.sendStatus & WON_SENT)) { |
There was a problem hiding this comment.
全部一緒に送ることを考えると最後の条件はいらないかなと。
(送れてきても、全部一緒に送ることで集計が楽になるはず)の
There was a problem hiding this comment.
時刻 0ms: AUCTION_INIT
↓ sendStatus = 0
時刻 100ms: BID_WON #1
↓ sendStatus & WON_SENT = 0 → キャッシュに追加
時刻 200ms: BID_WON #2
↓ sendStatus & WON_SENT = 0 → キャッシュに追加
時刻 300ms: AUCTION_END
↓ 800msタイマー開始
時刻 1100ms: sendWonBidsData() 実行
↓ BID_WON #1, #2 をまとめて送信
↓ sendStatus |= WON_SENT → sendStatus = 1
時刻 1500ms: BID_WON #3(遅延)
↓ sendStatus & WON_SENT = 1 → 即座に個別送信
時刻 2000ms: BID_WON #4(遅延)
↓ sendStatus & WON_SENT = 1 → 即座に個別送信
これが今なんですが
時刻 0ms: AUCTION_INIT
↓ sendStatus = 0
時刻 100ms: BID_WON #1
↓ sendStatus & WON_SENT = 0 → キャッシュに追加
時刻 200ms: BID_WON #2
↓ sendStatus & WON_SENT = 0 → キャッシュに追加
時刻 300ms: AUCTION_END
↓ 800msタイマー開始
時刻 1100ms: sendWonBidsData() 実行
↓ BID_WON #1, #2 をまとめて送信
時刻 1200ms: BID_WON #3
↓ sendStatus & WON_SENT = 0 → キャッシュに追加
時刻 1300ms: BID_WON #4
↓ sendStatus & WON_SENT = 0 → キャッシュに追加
時刻 1400ms: AUCTION_END
↓ 800msタイマー開始
時刻 1500ms: sendWonBidsData() 実行
↓ BID_WON #3, #4 をまとめて送信
この場合sendStatus,WON_SENT不要
みたいなかんじのほうが楽だよねってことであってますか
There was a problem hiding this comment.
というか単純にここでチェックしなくても問題なくねという話ですかね
There was a problem hiding this comment.
次のPRに書いたのですが、ここを直すと、 sendIndividualWonBid がいらなくなる認識でした
modules/imAnalyticsAdapter.js
Outdated
| function getConsentData(bidderRequests) { | ||
| if (!bidderRequests || !bidderRequests[0]) { | ||
| return EMPTY_CONSENT_DATA; | ||
| } | ||
|
|
There was a problem hiding this comment.
bidderRequests から取るより、Adapter から取得した方が分かりやすいかなと思ったのですが、どっちがいいっすかね・・?(0番目から取るよりという意味で。他のAnalytics Adapter はどうですか?)
There was a problem hiding this comment.
bidderRequestsから取得しているところを見ていたんですが
最近はちゃんと主流になっていたので全体を見直してAdapter利用するように修正しました!
modules/imAnalyticsAdapter.js
Outdated
| timestamp, | ||
| wonBids: auction.wonBids |
There was a problem hiding this comment.
少しでも小さくと・・・ ts, bids あたりで良いかもです。
modules/imAnalyticsAdapter.js
Outdated
|
|
||
| const DEFAULT_BID_WON_TIMEOUT = 800; // 0.8 second for initial batch | ||
| const DEFAULT_CID = 5126; | ||
| const API_BASE_URL = 'https://b6.im-apps.net/bids'; |
There was a problem hiding this comment.
(完全に趣味ですが)Prebid にあわせて、bid にしませんか?
…andlers into imAnalyticsAdapter
|
Tread carefully! This PR adds 1 linter warning (possibly disabled through directives):
|
modules/imAnalyticsAdapter.js
Outdated
| gdprApplies: gdprConsent.gdprApplies, | ||
| gdpr: gdprConsent.consentString, |
There was a problem hiding this comment.
| gdprApplies: gdprConsent.gdprApplies, | |
| gdpr: gdprConsent.consentString, | |
| gdpr: gdprConsent.gdprApplies ? 1 : 0, |
と短くしてなるべく小さくした方が良さげかなと。
| const gdprConsent = request.gdprConsent || {}; | ||
| const uspConsent = request.uspConsent; | ||
|
|
||
| return { |
modules/imAnalyticsAdapter.js
Outdated
|
|
||
| // If initial batch has been sent, send immediately | ||
| if (auction.sendStatus & WON_SENT) { | ||
| this.sendIndividualWonBid(auctionId, bidWonArgs, auction.consentData); |
There was a problem hiding this comment.
sendWonBidsData で送る(sendIndividualWonBid がいらなくなる)想定だったのですが、
だめでしたでしょうか?
pv, won の各送信処理は一箇所にまとめた方が良いかなと思いまして。
fecker
left a comment
There was a problem hiding this comment.
すません。細かいですが・・・ bidReqeust (いっぱい)なので、結構削減
modules/imAnalyticsAdapter.js
Outdated
| transformAucInitData(auctionArgs) { | ||
| return { | ||
| ts: auctionArgs.timestamp, | ||
| adUnitCount: (auctionArgs.adUnits || []).length |
There was a problem hiding this comment.
| adUnitCount: (auctionArgs.adUnits || []).length | |
| adUnits: (auctionArgs.adUnits || []).length |
なるべく小さく観点で減らしておきたいっす。
modules/imAnalyticsAdapter.js
Outdated
| pageUrl: window.location.href, | ||
| url: document.referrer || '', |
There was a problem hiding this comment.
| pageUrl: window.location.href, | |
| url: document.referrer || '', | |
| url: window.location.href, | |
| ref: document.referrer || '', |
すんません。こっちのイメージでした w
modules/imAnalyticsAdapter.js
Outdated
| import { EVENTS } from '../src/constants.js'; | ||
| import { sendBeacon } from '../src/ajax.js'; | ||
|
|
||
| const DEFAULT_BID_WON_TIMEOUT = 800; // 0.8 second for initial batch |
There was a problem hiding this comment.
悩み相談なのですが、ほんとにみんなこんなに早く返してるかな・・・
感覚値ですが 1500 でもいいかもと思ってきました・・・他はどうなんでしょうか・・・
There was a problem hiding this comment.
| アダプター | タイムアウト値 |
|---|---|
| 33acrossAnalyticsAdapter | 500ms |
| livewrappedAnalyticsAdapter | 500ms |
| r2b2AnalyticsAdapter | 500ms |
| imAnalyticsAdapter | 800ms |
| ooloAnalyticsAdapter | 1500ms |
| yandexAnalyticsAdapter | 1500ms |
| pubmaticAnalyticsAdapter | 2000ms |
| atsAnalyticsAdapter | 2000ms |
| concertAnalyticsAdapter | 3000ms |
| adxpremiumAnalyticsAdapter | 3500ms |
| adkernelAdnAnalyticsAdapter | 4000ms |
こんな感じでした。
1500くらいでもいいかもしれません
ここだけちょっとわからなかったですmm |
Number 入ります!と宣言してましたが、 toString() しておけば安心かな〜と思います w |
fecker
left a comment
There was a problem hiding this comment.
細かいとこですが、ちょっとconsent も短くしたくなったです!
bidWonTimeout は、いったん、1500でいきましょうか。
(意外と、みんな長めに取ってるので、2000 でもいい気もしてきてますが・・・優柔不断)
その他は良さげです。
modules/imAnalyticsAdapter.js
Outdated
| this.handleAucInitData(args); | ||
| }, | ||
|
|
||
| /** | ||
| * Handle auction init data - send immediately for PV tracking | ||
| * @param {Object} auctionArgs - Auction arguments | ||
| */ | ||
| handleAucInitData(auctionArgs) { | ||
| const consentData = cache.auctions[auctionArgs.auctionId].consentData; | ||
| const payload = { | ||
| url: window.location.href, | ||
| ref: document.referrer || '', | ||
| ...this.transformAucInitData(auctionArgs), | ||
| consentData | ||
| }; |
There was a problem hiding this comment.
| this.handleAucInitData(args); | |
| }, | |
| /** | |
| * Handle auction init data - send immediately for PV tracking | |
| * @param {Object} auctionArgs - Auction arguments | |
| */ | |
| handleAucInitData(auctionArgs) { | |
| const consentData = cache.auctions[auctionArgs.auctionId].consentData; | |
| const payload = { | |
| url: window.location.href, | |
| ref: document.referrer || '', | |
| ...this.transformAucInitData(auctionArgs), | |
| consentData | |
| }; | |
| this.handleAucInitData(args, consentData); | |
| }, | |
| /** | |
| * Handle auction init data - send immediately for PV tracking | |
| * @param {Object} auctionArgs - Auction arguments | |
| */ | |
| handleAucInitData(args, consent) { | |
| const payload = { | |
| url: window.location.href, | |
| ref: document.referrer || '', | |
| ...this.transformAucInitData(args), | |
| consent | |
| }; |
こっちは、cache からとるより、引数から渡した方が見通しが良いかなと思いました。
あと細かいですが、consentData も短くしちゃいましょうか!(bid request がどんくらいくるか怖くて・・・)
modules/imAnalyticsAdapter.js
Outdated
| const consentData = auction.consentData; | ||
| const ts = auction.auctionInitTimestamp || Date.now(); | ||
|
|
||
| auction.wonSent = true; | ||
| auction.wonBidsTimer = null; | ||
| const bids = auction.wonBids; | ||
| auction.wonBids = []; | ||
|
|
||
| sendToApi(buildApiUrlWithOptions(this.options, 'won', auctionId), { | ||
| consentData, | ||
| ts, | ||
| bids | ||
| }); |
There was a problem hiding this comment.
| const consentData = auction.consentData; | |
| const ts = auction.auctionInitTimestamp || Date.now(); | |
| auction.wonSent = true; | |
| auction.wonBidsTimer = null; | |
| const bids = auction.wonBids; | |
| auction.wonBids = []; | |
| sendToApi(buildApiUrlWithOptions(this.options, 'won', auctionId), { | |
| consentData, | |
| ts, | |
| bids | |
| }); | |
| const consent = auction.consentData; | |
| const ts = auction.auctionInitTimestamp || Date.now(); | |
| auction.wonSent = true; | |
| auction.wonBidsTimer = null; | |
| const bids = auction.wonBids; | |
| auction.wonBids = []; | |
| sendToApi(buildApiUrlWithOptions(this.options, 'won', auctionId), { | |
| bids, | |
| ts, | |
| consent, | |
| }); |
こちらも、consent と 短くしちゃいたいっす!
|
指摘いただいた点修正しました! |
Type of change
Bugfix
Feature
New bidder adapter
Updated bidder adapter
Code style update (formatting, local variables)
Refactoring (no functional changes, no api changes)
Build related changes
CI related changes
Does this change affect user-facing APIs or examples documented on http://prebid.org?
Other
Description of change
Other information